package com.huhao.wshare.service.impl;

import com.huhao.wshare.dto.Dynamic.CommentDTO;
import com.huhao.wshare.dto.Dynamic.DynamicCreateDTO;
import com.huhao.wshare.dto.Dynamic.DynamicDTO;
import com.huhao.wshare.dto.Dynamic.VideoInfoDTO;
import com.huhao.wshare.dto.User.UserInfoDTO;
import com.huhao.wshare.entity.*;
import com.huhao.wshare.repository.*;
import com.huhao.wshare.service.DynamicService;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import com.huhao.wshare.dto.Dynamic.CommentCreateDTO;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class DynamicServiceImpl implements DynamicService {

    private final DynamicRepository dynamicRepository;
    private final UserRepository userRepository;
    private final LikeRepository likeRepository;
    private final CommentRepository commentRepository;
    // --- 1. 注入 FriendsRepository 用于查询好友备注 ---
    private final FriendsRepository friendsRepository;


    @Override
    @Transactional
    public DynamicDTO createDynamic(Long userId, DynamicCreateDTO createDTO) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new EntityNotFoundException("用户不存在, id: " + userId));

        Dynamic dynamic = new Dynamic();
        dynamic.setUser(user);

        // 调用辅助方法填充内容
        populateDynamicContents(dynamic, createDTO);

        Dynamic savedDynamic = dynamicRepository.save(dynamic);
        return convertToDTO(savedDynamic, userId);
    }


    @Override
    @Transactional
    public void deleteDynamic(Long userId, Long dynamicId) {
        Dynamic dynamic = dynamicRepository.findById(dynamicId)
                .orElseThrow(() -> new EntityNotFoundException("动态不存在, id: " + dynamicId));

        if (!dynamic.getUser().getId().equals(userId)) {
            throw new SecurityException("无权删除他人的动态");
        }
        dynamicRepository.delete(dynamic);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<DynamicDTO> getFriendDynamics(Long userId, Pageable pageable) {
        // 假设 findFriendDynamicsByUserId 已经实现
        Page<Dynamic> dynamicPage = dynamicRepository.findFriendDynamicsByUserId(userId, pageable);
        return dynamicPage.map(dynamic -> convertToDTO(dynamic, userId));
    }

    @Override
    @Transactional(readOnly = true)
    public Page<DynamicDTO> getUserDynamics(Long targetUserId, Long currentUserId, Pageable pageable) {
        Page<Dynamic> dynamicPage = dynamicRepository.findByUserId(targetUserId, pageable);
        return dynamicPage.map(dynamic -> convertToDTO(dynamic, currentUserId));
    }

    // --- 2. 【核心修改】重构 convertToDTO 方法以使用新的辅助方法 ---
    private DynamicDTO convertToDTO(Dynamic dynamic, Long currentUserId) {
        DynamicDTO dto = new DynamicDTO();
        dto.setId(dynamic.getId());
        // 使用新的辅助方法转换作者信息，包含备注和性别
        dto.setAuthor(convertUserToUserInfoDTO(dynamic.getUser(), currentUserId));
        dto.setCreateTime(dynamic.getCreateTime());

        // 遍历并设置不同类型的内容 (文本、图片、视频)
        for (DynamicContent content : dynamic.getContents()) {
            switch (content.getContentType()) {
                case "TEXT":
                    dto.setTextContent(content.getContentText());
                    break;
                case "IMAGE":
                    dto.setImageUrls(content.getImages().stream()
                            .map(DynamicImage::getImageUrl)
                            .collect(Collectors.toList()));
                    break;
                case "VIDEO":
                    if (!CollectionUtils.isEmpty(content.getVideos())) {
                        DynamicVideo video = content.getVideos().get(0);
                        VideoInfoDTO videoInfoDTO = new VideoInfoDTO();
                        videoInfoDTO.setVideoUrl(video.getVideoUrl());
                        videoInfoDTO.setCoverImageUrl(video.getCoverImageUrl());
                        dto.setVideo(videoInfoDTO);
                    }
                    break;
            }
        }
        // 确保 imageUrls 列表不为 null
        if (dto.getImageUrls() == null) {
            dto.setImageUrls(Collections.emptyList());
        }

        // 设置点赞用户列表，同样使用新辅助方法
        dto.setLikers(dynamic.getLikes().stream()
                .map(like -> convertUserToUserInfoDTO(like.getUser(), currentUserId))
                .collect(Collectors.toList()));

        // 判断当前用户是否已点赞
        dto.setLikedByCurrentUser(dynamic.getLikes().stream()
                .anyMatch(like -> like.getUser().getId().equals(currentUserId)));

        // 设置评论列表，使用新的辅助方法转换，以包含评论者的完整信息
        dto.setComments(dynamic.getComments().stream()
                .map(comment -> convertCommentToCommentDTO(comment, currentUserId))
                .collect(Collectors.toList()));

        return dto;
    }

    // --- 3. 【新增辅助方法】将 User 转换为包含备注和性别的 UserInfoDTO ---
    private UserInfoDTO convertUserToUserInfoDTO(User user, Long currentUserId) {
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setId(user.getId());
        userInfoDTO.setUsername(user.getUsername());
        userInfoDTO.setAvatar(user.getAvatar());
        userInfoDTO.setSigns(user.getSigns());
        // 设置性别
        userInfoDTO.setGender(user.getGender());

        // 如果要转换的用户不是当前登录用户，则查询好友关系以获取备注
        if (!user.getId().equals(currentUserId)) {
            // 使用 getReferenceById 避免完整加载当前用户实体，提高效率
            User currentUserProxy = userRepository.getReferenceById(currentUserId);
            // 状态为1表示是已确认的好友
            Optional<Friends> friendship = friendsRepository.findByUserAndFriendAndStatus(currentUserProxy, user, 1);
            friendship.ifPresent(f -> userInfoDTO.setRemark(f.getRemark()));
        }

        return userInfoDTO;
    }

    // --- 4. 【新增辅助方法】将 Comment 转换为 CommentDTO，并处理作者信息 ---
    private CommentDTO convertCommentToCommentDTO(Comment comment, Long currentUserId) {
        CommentDTO commentDTO = new CommentDTO();
        commentDTO.setId(comment.getId());
        commentDTO.setContent(comment.getContent());
        commentDTO.setCreateTime(comment.getCreateTime());
        // 转换评论的作者信息，同样包含备注和性别
        commentDTO.setAuthor(convertUserToUserInfoDTO(comment.getUser(), currentUserId));

        // 如果有回复对象，同样进行转换 (假设 CommentDTO 中有 repliedTo 字段)
        // if (comment.getRepliedTo() != null) {
        //     commentDTO.setRepliedTo(convertUserToUserInfoDTO(comment.getRepliedTo(), currentUserId));
        // }

        return commentDTO;
    }


    @Override
    @Transactional
    public void likeDynamic(Long userId, Long dynamicId) {
        if (likeRepository.existsByUserIdAndDynamicId(userId, dynamicId)) {
            return;
        }
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new EntityNotFoundException("用户不存在, id: " + userId));
        Dynamic dynamic = dynamicRepository.findById(dynamicId)
                .orElseThrow(() -> new EntityNotFoundException("动态不存在, id: " + dynamicId));

        Like like = new Like();
        like.setUser(user);
        like.setDynamic(dynamic);
        likeRepository.save(like);
    }

    @Override
    @Transactional
    public void unlikeDynamic(Long userId, Long dynamicId) {
        Like like = likeRepository.findByUserIdAndDynamicId(userId, dynamicId)
                .orElseThrow(() -> new EntityNotFoundException("您尚未点赞，无法执行取消点赞操作"));

        likeRepository.delete(like);
    }

    @Override
    @Transactional
    public CommentDTO addComment(Long userId, Long dynamicId, CommentCreateDTO createDTO) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new EntityNotFoundException("用户不存在, id: " + userId));
        Dynamic dynamic = dynamicRepository.findById(dynamicId)
                .orElseThrow(() -> new EntityNotFoundException("动态不存在, id: " + dynamicId));

        Comment comment = new Comment();
        comment.setUser(user);
        comment.setDynamic(dynamic);
        comment.setContent(createDTO.getContent());

        Comment savedComment = commentRepository.save(comment);
        // 返回转换后的 DTO
        return convertCommentToCommentDTO(savedComment, userId);
    }

    @Override
    @Transactional
    public CommentDTO updateComment(Long userId, Long commentId, CommentCreateDTO updateDTO) {
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new EntityNotFoundException("评论不存在, id: " + commentId));

        // 权限校验：只有评论作者才能修改
        if (!comment.getUser().getId().equals(userId)) {
            throw new AccessDeniedException("只有评论作者才能修改该评论");
        }

        comment.setContent(updateDTO.getContent());
        Comment updatedComment = commentRepository.save(comment);
        // 返回转换后的 DTO
        return convertCommentToCommentDTO(updatedComment, userId);
    }

    @Override
    @Transactional
    public void deleteComment(Long userId, Long commentId) {
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new EntityNotFoundException("评论不存在, id: " + commentId));

        Long commentAuthorId = comment.getUser().getId();
        Long dynamicAuthorId = comment.getDynamic().getUser().getId();

        // 权限校验：当前用户既不是评论作者，也不是动态发布者
        if (!userId.equals(commentAuthorId) && !userId.equals(dynamicAuthorId)) {
            throw new AccessDeniedException("只有评论作者或动态发布者才能删除该评论");
        }

        commentRepository.delete(comment);
    }
    /**
     * 【新增】修改动态
     */
    @Override
    @Transactional
    public DynamicDTO updateDynamic(Long userId, Long dynamicId, DynamicCreateDTO updateDTO) {
        // 1. 查找动态实体
        Dynamic dynamic = dynamicRepository.findById(dynamicId)
                .orElseThrow(() -> new EntityNotFoundException("动态不存在, id: " + dynamicId));

        // 2. 权限验证
        if (!dynamic.getUser().getId().equals(userId)) {
            throw new AccessDeniedException("无权修改他人的动态");
        }

        // 3. 清空旧的内容
        dynamic.getContents().clear();

        // 4. 【核心修复】立即将删除操作同步到数据库
        // 这会执行所有待处理的 SQL DELETE 语句，确保数据库中的旧记录被清除。
        dynamicRepository.flush();

        // 5. 现在数据库干净了，可以安全地填充和插入新的内容
        populateDynamicContents(dynamic, updateDTO);

        // 6. 保存更新后的动态
        Dynamic updatedDynamic = dynamicRepository.save(dynamic);

        // 7. 转换并返回 DTO
        return convertToDTO(updatedDynamic, userId);
    }
    /**
     * 【新增辅助方法】
     * 从 DTO 中提取内容并填充到 Dynamic 实体中。
     * 此方法被 createDynamic 和 updateDynamic 复用。
     * @param dynamic 要被填充的 Dynamic 实体
     * @param dto 包含新内容的数据传输对象
     */
    private void populateDynamicContents(Dynamic dynamic, DynamicCreateDTO dto) {
        int contentOrder = 0;

        // 1. 处理文本内容
        if (StringUtils.hasText(dto.getTextContent())) {
            DynamicContent textContent = new DynamicContent();
            textContent.setDynamic(dynamic);
            textContent.setContentType("TEXT");
            textContent.setContentText(dto.getTextContent());
            textContent.setContentOrder(contentOrder++);
            dynamic.getContents().add(textContent);
        }

        // 2. 处理图片内容
        if (!CollectionUtils.isEmpty(dto.getImageUrls())) {
            DynamicContent imageContentBlock = new DynamicContent();
            imageContentBlock.setDynamic(dynamic);
            imageContentBlock.setContentType("IMAGE");
            imageContentBlock.setContentOrder(contentOrder++);

            AtomicInteger imageOrder = new AtomicInteger(0);
            List<DynamicImage> images = dto.getImageUrls().stream().map(url -> {
                DynamicImage image = new DynamicImage();
                image.setDynamicContent(imageContentBlock);
                image.setImageUrl(url);
                image.setImageOrder(imageOrder.getAndIncrement());
                return image;
            }).collect(Collectors.toList());

            imageContentBlock.getImages().addAll(images);
            dynamic.getContents().add(imageContentBlock);
        }

        // 3. 处理视频内容
        if (dto.getVideo() != null && StringUtils.hasText(dto.getVideo().getVideoUrl())) {
            DynamicContent videoContentBlock = new DynamicContent();
            videoContentBlock.setDynamic(dynamic);
            videoContentBlock.setContentType("VIDEO");
            videoContentBlock.setContentOrder(contentOrder++);

            DynamicVideo video = new DynamicVideo();
            video.setDynamicContent(videoContentBlock);
            video.setVideoUrl(dto.getVideo().getVideoUrl());
            video.setCoverImageUrl(dto.getVideo().getCoverImageUrl());
            video.setVideoOrder(0);

            videoContentBlock.getVideos().add(video);
            dynamic.getContents().add(videoContentBlock);
        }
    }
}
